#include <stdlib.h>
#include <fxlib.h>

#include "config.h"
#include "console.h"

#define WIDTH 128
#define HEIGHT 64

#define menu_free_item(item) if(item) free(item->str)

extern int* get_tex_flag_address();

int test;

void draw_menu(Menu* menu)
{
	int x, y, i, key;
	int longest = 0, tmp;
	int border = 1, margin = 2, check_box_width = 15, item_height = 7, letter_width = 4;// inter_line = 1;
	int cursor_y = 0;
	DISPBOX box;

	for(i=0; i < menu->items_number; i++) {
		tmp = strlen(menu->items[i]->str) * letter_width;
		if(menu->items[i]->type == CHECK_BOX) tmp += check_box_width;

		if(tmp > longest) longest = tmp;
	}

	box.left = (WIDTH/2) - (longest/2) - margin - border;
	box.right = box.left + longest + 2*margin + 2*border;
	box.bottom = (HEIGHT/2) + (menu->items_number * item_height)/2 /*+ margin*/ + border;
	box.top = HEIGHT - box.bottom;

	Bdisp_AreaClr_VRAM(&box);

	Bdisp_AreaReverseVRAM(box.left, box.top, box.right, box.bottom);

	Bdisp_AreaReverseVRAM(box.left + border, box.top + border, box.right - border, box.bottom - border);

	while (key != KEY_CTRL_EXIT) {
		for(i=0; i < menu->items_number; i++) {
			PrintMini(box.left + border + margin, box.top + margin + item_height*i, (unsigned char*)menu->items[i]->str, MINI_OVER);
			if(menu->items[i]->type == CHECK_BOX) {
				if((menu->items[i]->action.val.value)) {
					if(*(menu->items[i]->action.val.value)) PrintMini(box.right - border - margin - (check_box_width/2) , box.top + margin + item_height*i, (unsigned char*)"[x]", MINI_OVER);
					else PrintMini(box.right - border - margin - (check_box_width/2) , box.top + margin + item_height*i, (unsigned char*)"[ ]", MINI_OVER);
				}
			}
		}
		PrintMini(box.left + border + margin, box.top + margin + item_height*cursor_y, (unsigned char*)menu->items[cursor_y]->str, MINI_REV);
		if(menu->items[cursor_y]->type == CHECK_BOX) {
			if((menu->items[cursor_y]->action.val.value)) {
				if(*(menu->items[cursor_y]->action.val.value)) PrintMini(box.right - border - margin - (check_box_width/2) , box.top + margin + item_height*cursor_y, (unsigned char*)"[x]", MINI_OVER);
				else PrintMini(box.right - border - margin - (check_box_width/2) , box.top + margin + item_height*cursor_y, (unsigned char*)"[ ]", MINI_OVER);
			}
		}
		GetKey(&key);
		
		if (key == KEY_CTRL_DOWN && cursor_y < menu->items_number-1) cursor_y++;	
		if (key == KEY_CTRL_UP && cursor_y > 0) cursor_y--;

		if (key == KEY_CTRL_EXE) {
			//menu_test();
			if(menu->items[cursor_y]->type == CHECK_BOX) {
				if(menu->items[cursor_y]->action.val.value != NULL) { //Changing the state of the variable, as a boolean
					if(*(menu->items[cursor_y]->action.val.value)) *(menu->items[cursor_y]->action.val.value) = 0;
					else *(menu->items[cursor_y]->action.val.value) = 1;

					if (menu->items[cursor_y]->action.val.save_function != NULL) (*menu->items[cursor_y]->action.val.save_function)();
				}
			}
			else if(menu->items[cursor_y]->type == FUNCTION_CALL) {
				if(menu->items[cursor_y]->action.function != NULL) {
					(*(menu->items[cursor_y]->action.function))(); //Calling the function
					break;
				}
			}
		}
	}
}

void menu_setup()
{
	int number = 2;
	Menu menu;
	menu.items = malloc(sizeof(Menu_Item*) * number);

	menu.items[0] = menu_create_item("About", FUNCTION_CALL, menu_about, (void*)NULL);
	menu.items[1] = menu_create_item("Pretty Print", CHECK_BOX, get_tex_flag_address(), save_config);
	if(menu.items[0] && menu.items[1]) menu.items_number = number;
	else {
		menu_free_item(menu.items[0]);
		menu_free_item(menu.items[1]);
	}

	draw_menu(&menu);

	menu_free_item(menu.items[0]);
	menu_free_item(menu.items[1]);
	free(menu.items);
}

void menu_about()
{
	int key;
	PopUpWin(6);
	PrintMini(12, 6, (unsigned char*)"Eigenmath symbolic maths", MINI_OVER);
	PrintMini(51, 14, (unsigned char*)"engine", MINI_OVER);
	PrintMini(12, 22, (unsigned char*)"Ported by Mike.", MINI_OVER);
	PrintMini(12, 30, (unsigned char*)"Enhanced by Nemh and the", MINI_OVER);
	PrintMini(38, 38, (unsigned char*)"PC community.", MINI_OVER);
	PrintMini(40, 46, (unsigned char*)"Early build", MINI_OVER);
	PrintMini(12, 54, (unsigned char*)"See : http://huit.re/eigen", MINI_OVER);
	GetKey(&key);
	return;
}

Menu_Item* menu_create_item(const char* str, Menu_Item_Type type, void* other, void* save_func)
{
	Menu_Item* item = malloc(sizeof(Menu_Item));
	if(item == NULL) return NULL;

	item->str = malloc(sizeof(char)*(strlen(str) + 1));
	if(item->str == NULL) {
		free(item);
		return NULL;
	}
	else strcpy(item->str, str);

	item->type = type;

	if(type == CHECK_BOX) {
		item->action.val.value = other;
		item->action.val.save_function = save_func;
	}
	else if(type == FUNCTION_CALL) item->action.function = other;

	return item;
}

void save_config()
{
	memory_save(CONFIG_FILE, (int*)get_tex_flag_address(), 4);
}

void load_config()
{
	if(memory_exists(CONFIG_FILE)) *(int*)(get_tex_flag_address()) = *((int*)memory_load(CONFIG_FILE));
}